package org.seedltd.upms.service.impl.sys;

import java.util.*;

import org.seedltd.base.exception.BusinessException;
import org.seedltd.core.base.BaseServiceImpl;
import org.seedltd.core.mybatis.conditions.ProQuery;
import org.seedltd.core.utils.tree.TreeUtil;
import org.seedltd.springsecurity.utils.UserUtils;
import org.seedltd.upms.constant.GlobalConst;
import org.seedltd.upms.mapper.sys.SysMenuMapper;
import org.seedltd.upms.model.sys.common.SelectTreeVO;
import org.seedltd.upms.model.sys.entity.SysMenu;
import org.seedltd.upms.model.sys.form.SysMenuForm;
import org.seedltd.upms.model.sys.form.SysMenuSearchForm;
import org.seedltd.upms.model.sys.vo.MenuMetaVO;
import org.seedltd.upms.model.sys.vo.SysMenuVO;
import org.seedltd.upms.model.sys.vo.UserMenuVO;
import org.seedltd.upms.service.sys.SysMenuService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import lombok.AllArgsConstructor;

/**
 * 系统菜单业务实现
 *
 * @author laizuan
 * @since 2021/07/19
 */
@Service
@AllArgsConstructor
public class SysMenuServiceImpl extends BaseServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    @Override
    public SysMenuVO findById(Long id) {
        return ProQuery.Builder(baseMapper).build().eq(SysMenu::getMenuId, id).selectOne(SysMenuVO.class);
    }

    @Override
    public Long add(SysMenuForm form) {
        SysMenu pojo = u().save(form, new SysMenu());
        return pojo.getMenuId();
    }

    @Override
    public boolean update(SysMenuForm form) {
        return u().updateById(form, form.getMenuId());
    }

    @Override
    @Transactional
    public boolean delete(Long id) {
        Integer count = baseMapper.checkHasChildren(id);
        if (count != null) {
            throw new BusinessException("菜单存在子级菜单，请先删除子级菜单后重试。");
        }
        baseMapper.deleteMenuRoleByMenuId(id);
        return baseMapper.deleteById(id) > 0;
    }

    @Override
    public List<SysMenuVO> page(SysMenuSearchForm searchForm) {
        List<SysMenuVO> menuVOList =
            ProQuery.Builder(baseMapper).searchForm(searchForm).build().selectList(SysMenuVO.class);
        return new TreeUtil<SysMenuVO>().build(menuVOList);
    }

    @Override
    public List<UserMenuVO> listUserMenu() {
        List<SysMenuVO> userMenus = baseMapper.listUserMenu(UserUtils.getUserId());
        if (CollectionUtils.isEmpty(userMenus)) {
            // throw new BusinessException("抱歉，您没有权限！请联系管理员授权后重试。");
            return null;
        }
        List<UserMenuVO> result = new ArrayList<>();
        Iterator<SysMenuVO> it = userMenus.iterator();
        UserMenuVO first;
        while (it.hasNext()) {
            SysMenuVO next = it.next();
            if (next.getParentId() == null || next.getParentId() == 0) {
                first = new UserMenuVO();
                first.setMenuId(next.getMenuId());
                first.setMeta(new MenuMetaVO(next.getMenuName(), next.getIcon()));
                first.setDisplay(GlobalConst.YES.equals(next.getDisplay()));
                first.setRouterName(next.getRouterName());
                first.setUrl(next.getUrl());
                result.add(first);
                it.remove();
            }
        }
        for (UserMenuVO userMenuVO : result) {
            List<UserMenuVO> children = buildChildrenItem(userMenus, userMenuVO);
            userMenuVO.setChildren(children);
        }

        return result;
    }

    private List<UserMenuVO> buildChildrenItem(List<SysMenuVO> userMenus, UserMenuVO userMenuVO) {
        if (CollectionUtils.isEmpty(userMenus)) {
            return new ArrayList<>();
        }
        List<UserMenuVO> children = new ArrayList<>();
        UserMenuVO menu;
        Iterator<SysMenuVO> iterator = userMenus.iterator();
        while (iterator.hasNext()) {
            SysMenuVO userMenu = iterator.next();
            if (userMenu.getMenuType() != 3 && userMenuVO.getMenuId().equals(userMenu.getParentId())) {
                menu = new UserMenuVO();
                menu.setUrl(userMenu.getUrl());
                menu.setMenuId(userMenu.getMenuId());
                menu.setComponentPath(userMenu.getComponentPath());

                if (userMenu.getMenuType() == 2) {
                    menu.setMeta(new MenuMetaVO(userMenu.getMenuName(), userMenu.getIcon(), userMenu.getNoCache(),
                        userMenu.getI18n(), getPermissions(userMenus, userMenu), userMenu.getActiveMenu()));
                }
                menu.setDisplay(GlobalConst.YES.equals(userMenu.getDisplay()));
                menu.setRouterName(userMenu.getRouterName());
                children.add(menu);
                iterator.remove();
            }
        }

        for (UserMenuVO child : children) {
            List<UserMenuVO> userMenuVOS = buildChildrenItem(userMenus, child);
            child.setChildren(userMenuVOS);
        }

        if (children.size() == 0) {
            return new ArrayList<>();
        }
        return children;
    }

    private Set<String> getPermissions(List<SysMenuVO> userMenus, SysMenuVO userMenu) {
        if (CollectionUtils.isEmpty(userMenus)) {
            return null;
        }

        Iterator<SysMenuVO> iterator = userMenus.iterator();
        Set<String> permissions = new HashSet<>();
        while (iterator.hasNext()) {
            SysMenuVO next = iterator.next();
            if (next.getMenuType() == 3 && userMenu.getMenuId().equals(next.getParentId())) {
                permissions.add(next.getPermission());
            }
        }
        return permissions;
    }

    @Override
    public List<SelectTreeVO> listSelectTreeMenu() {
        List<SelectTreeVO> selectTreeMenus = baseMapper.listSelectTreeMenu();
        return new TreeUtil<SelectTreeVO>().build(selectTreeMenus);
    }
}